package panda.client.ui.widgets;

import panda.client.Cardpanda;
import panda.client.JSNI;
import panda.client.engine.Observable;
import panda.client.engine.Observer;
import panda.client.ui.observable.ObservableLifeTotal;

import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseDownHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.event.dom.client.MouseUpEvent;
import com.google.gwt.event.dom.client.MouseUpHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;

public class LifeCounter extends Composite implements Observer {
	private HorizontalPanel shell = new HorizontalPanel();
	private HTML decLife = new HTML("&ndash;");
	private HTML incLife = new HTML("+");
	private Label lifeTotal = new Label("");
	private String owner;

	public LifeCounter(final ObservableLifeTotal observableLifeTotal) {
		observableLifeTotal.addObserver(this);
		this.owner = observableLifeTotal.getOwnerName();

		JSNI.disableSelection(decLife.getElement());
		JSNI.disableSelection(incLife.getElement());
		JSNI.disableSelection(lifeTotal.getElement());

		DOM.setStyleAttribute(decLife.getElement(), "padding", "3px");
		DOM.setStyleAttribute(decLife.getElement(), "borderRight", "1px solid rgb(180, 180, 180)");
		DOM.setStyleAttribute(incLife.getElement(), "padding", "3px");
		DOM.setStyleAttribute(incLife.getElement(), "borderLeft", "1px solid rgb(180, 180, 180)");

		DOM.setStyleAttribute(lifeTotal.getElement(), "textAlign", "center");
		DOM.setStyleAttribute(lifeTotal.getElement(), "padding", "3px");

		DOM.setStyleAttribute(shell.getElement(), "border", "1px solid rgb(180, 180, 180)");
		// shell.addStyleName("lifeCounter-RoundedBorder");

		/* Mouse Handlers for decLife, the life decrement label */
		decLife.addMouseDownHandler(new MouseDownHandler() {
			public void onMouseDown(MouseDownEvent event) {
				setMouseDownStyles(decLife);
			}
		});

		decLife.addMouseOverHandler(new MouseOverHandler() {
			public void onMouseOver(MouseOverEvent event) {
				setMouseEnterStyles(decLife);
			}
		});

		decLife.addMouseOutHandler(new MouseOutHandler() {
			public void onMouseOut(MouseOutEvent event) {
				setMouseLeaveStyles(decLife);
			}
		});

		decLife.addMouseUpHandler(new MouseUpHandler() {
			public void onMouseUp(MouseUpEvent event) {
				observableLifeTotal.setLifeTotal(observableLifeTotal.getLifeTotal() - 1);
				setMouseUpStyles(decLife);

				String name = Cardpanda.clientModel.getSessionID().getName();
				String logForMe = "You decrement " + owner + "'s life total.  New life total: "
						+ observableLifeTotal.getLifeTotal();
				String logForOthers = name + " decrements " + owner + "'s life total.  New life total: "
						+ observableLifeTotal.getLifeTotal();
				NoteTip.get().log(logForMe, logForOthers);

				Cardpanda.sendModelUpdateToServer(Cardpanda.clientModel.getSessionID());
			}
		});

		/*
		 * The incLife mouse handlers are done differently for the sake of science. One day, if I find out one way is
		 * better than the other, I will change both to accomodate that. Right now, the incLife way of creating a separate
		 * mouse handler class seems more modular, but it is messier and requires code separation.
		 */
		
		/* Mouse Handlers for incLife, the life increment label */
		incLife.addMouseDownHandler(new incLifeMouseHandler(observableLifeTotal));
		incLife.addMouseUpHandler(new incLifeMouseHandler(observableLifeTotal));
		incLife.addMouseOutHandler(new incLifeMouseHandler(observableLifeTotal));
		incLife.addMouseOverHandler(new incLifeMouseHandler(observableLifeTotal));

		shell.add(decLife);
		shell.add(lifeTotal);
		shell.add(incLife);
		initWidget(shell);
		update(observableLifeTotal, null);
	}

	private void setMouseUpStyles(Label incDec) {
		DOM.setStyleAttribute(incDec.getElement(), "backgroundColor", "rgb(230, 230, 230)");
	}

	private void setMouseDownStyles(Label incDec) {
		DOM.setStyleAttribute(incDec.getElement(), "backgroundColor", "rgb(240, 240, 240)");
	}

	private void setMouseEnterStyles(Label incDec) {
		DOM.setStyleAttribute(incDec.getElement(), "backgroundColor", "rgb(230, 230, 230)");
		DOM.setStyleAttribute(incDec.getElement(), "cursor", "pointer");
	}

	private void setMouseLeaveStyles(Label incDec) {
		DOM.setStyleAttribute(incDec.getElement(), "backgroundColor", "white");
		DOM.setStyleAttribute(incDec.getElement(), "cursor", "default");
	}

	public void update(Observable o, Object arg) {
		ObservableLifeTotal life = (ObservableLifeTotal) o;
		lifeTotal.setText(life.getLifeTotal() + "");
	}

	public String getOwner() {
		return owner;
	}

	private class incLifeMouseHandler implements MouseOverHandler, MouseDownHandler, MouseUpHandler, MouseOutHandler {
		ObservableLifeTotal observableLifeTotal;

		public incLifeMouseHandler(final ObservableLifeTotal observableLifeTotal) {
			this.observableLifeTotal = observableLifeTotal;
		}

		public void onMouseDown(MouseDownEvent event) {
			setMouseDownStyles(incLife);
		}

		public void onMouseOver(MouseOverEvent event) {
			setMouseEnterStyles(incLife);
		}

		public void onMouseOut(MouseOutEvent event) {
			setMouseLeaveStyles(incLife);
		}

		public void onMouseUp(MouseUpEvent event) {
			int newTotal = observableLifeTotal.getLifeTotal() + 1;
			observableLifeTotal.setLifeTotal(newTotal);
			setMouseUpStyles(incLife);

			String name = Cardpanda.clientModel.getSessionID().getName();
			String logForMe = "You increment " + owner + "'s life total.  New life total: "
					+ observableLifeTotal.getLifeTotal();
			String logForOthers = name + " increments " + owner + "'s life total.  New life total: "
					+ observableLifeTotal.getLifeTotal();
			NoteTip.get().log(logForMe, logForOthers);

			Cardpanda.sendModelUpdateToServer(Cardpanda.clientModel.getSessionID());
		}
	}
}